/* 						-*- coding: utf-8 -*-
* @brief : Une version de tokenize
* @author : Mathieu RUL
* @version : 1
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "tokenize.h"
#include "environ.h"
#define LINE_SIZE 1000

static char current_line[LINE_SIZE];
static unsigned current_index;
static size_t size;
static enum token_type next_type;

struct token *get_parsed_token(const char quote) {
	struct token *result = NULL;
	result = (struct token*)malloc(sizeof(struct token));
	unsigned i = 0;
	char current_word[MAX_TOKEN] = {'\0'};
	if('$' == quote) {
		while ('\0' != current_line[current_index] && ' ' != current_line[current_index] && ';' != current_line[current_index] && current_index < size) {
			current_word[i++] = current_line[current_index++];
		}
		strcpy(current_word, get_environ(current_word));
	} else {
		while ('\0' != current_line[current_index] && quote != current_line[current_index] && current_index < size) {
			if('\\' == current_line[current_index] && quote == current_line[current_index+1]) {
				current_word[strlen(current_word)] = quote;
				current_index++;
			}
			else {
				current_word[strlen(current_word)] = current_line[current_index];
			}
			current_index++;
		}
		if('\0' == current_line[current_index]) {
			result->type = error;
			result->content = "Quote not closed";
			next_type = eol;
			return result;
		}
	}
	current_index++;
	if('\n' == current_word[strlen(current_word)-1]) current_word[strlen(current_word)-1] = '\0';
	if('\0' == current_line[current_index]) next_type = eol;
	result->content = (char*)malloc((strlen(current_word)+1) * sizeof(char));
	result->type = item;
	strcpy(result->content, current_word);
	return result;
}

struct token *get_current_token(const enum token_type type, const char *current_word){
	struct token *result = NULL;
	result = (struct token*)malloc(sizeof(struct token));
	result->content = NULL;
	if(strlen(current_word)) {
		result->content = (char*)malloc((strlen(current_word)+1) * sizeof(char));
		result->type =  item;
		strcpy(result->content, current_word);
		next_type = type;
	} else {
		result->type = type;
	}
	return result;
}

struct token *get_token(char *line) {
	struct token *result = NULL;
	char current_word[MAX_TOKEN] = {'\0'};
	if (NULL != line){
		next_type = item;
		current_index = 0;
		strcpy(current_line, line);
		size = strlen(line);
	}
	if(item != next_type) {
		result = (struct token*)malloc(sizeof(struct token));
		result->type =  next_type;
		next_type = item;
		return result;
	}
	while (current_index < size) {
		switch(current_line[current_index++]) {
		case '\t':
			break;
		case '<':
			result = get_current_token(less, current_word);
			return result;
			break;
		case '>':
			if('\0' != current_line[current_index] && '>' == current_line[current_index]) {
				result = get_current_token(append, current_word);
				current_index++;
			} else {
				result = get_current_token(greater, current_word);
			}
			return result;
			break;
		case ';':
			result = get_current_token(semicolon, current_word);
			return result;
			break;
		case '|':
			result = get_current_token(pip, current_word);
			return result;
			break;
		case '&':
			result = get_current_token(amper, current_word);
			return result;
			break;
	    case '\0':
		case '\n':
			result = get_current_token(eol, current_word);
			printf("\\n\n");
			return result;
		case ' ':
			if(1 < current_index) {
				result = get_current_token(item, current_word);
				if(result->content)
				return result;
			}
			break;
		case '\'':
		case '"':
		case '$':
			if(1 == current_index || (1 < current_index && ('<' == current_line[current_index-2]
									|| '>' == current_line[current_index-2]
									|| ';' == current_line[current_index-2]
									|| '|' == current_line[current_index-2]
									|| '&' == current_line[current_index-2]
									|| ' ' == current_line[current_index-2]
									|| current_line[current_index-1] == current_line[current_index-2]))) {
				result = get_parsed_token(current_line[current_index-1]);
				return result;
			} else {
				current_word[strlen(current_word)] = current_line[current_index-1];
			}
			break;
		case '#':
			result = get_current_token(eol, current_word);
			return result;
			break;
		default:
			current_word[strlen(current_word)] = current_line[current_index-1];
		}
	}
	result = get_current_token(eol, current_word);
	return result;
}
